// ShapeView.cpp : implementation file
//

#include "stdafx.h"
#include "U7FileTool.h"

#include "ShapeDoc.h"
#include "ShapeView.h"

#include "Shape.h"

// CShapeView

IMPLEMENT_DYNCREATE(CShapeView, CScrollView)

CShapeView::CShapeView()
{
	m_pCurShape = NULL;
	m_pGraphic = NULL;
	m_pDragImage = NULL;
	m_bDragged = false;
}

CShapeView::~CShapeView()
{
	if ( m_pGraphic )
		DeleteGraphic(m_pGraphic);
	if ( m_pDragImage )
		DeleteGraphic(m_pDragImage);
}


BEGIN_MESSAGE_MAP(CShapeView, CScrollView)
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_KEYDOWN()
END_MESSAGE_MAP()


// CShapeView drawing

void DrawShapeList( PGRAPHIC pGraphic, PSHAPEENTRY shapeEntry, long shapeLength )
{
	ClearGraphic(pGraphic);

	int nFrameCount = GetShapeFrameCount( shapeEntry, shapeLength );
	if ( IsShapeTile( shapeEntry, shapeLength ) )
	{
		int x = TILE_WIDTH-1;
		for ( int i = 0; i < nFrameCount; i++ )
		{
			TILE tile = GetShapeTile( shapeEntry, shapeLength, i );
			DrawShapeTile( pGraphic, tile, x, TILE_HEIGHT-1 );
			x += TILE_WIDTH;
		}
	}
	else
	{
		int x = 0;
		int y = 0;
		int maxY = 0;
		for ( int i = 0; i < nFrameCount; i++ )
		{
			PFRAMEENTRY frameEntry = GetShapeFrame( shapeEntry, shapeLength, i );
			POINT hotspot;
			SIZE dimension;
			GetShapeFrameInfo( frameEntry, hotspot, dimension );
			DrawShapeFrame( pGraphic, frameEntry, x + hotspot.x, y + hotspot.y );

			if ( dimension.cy > maxY )
				maxY = dimension.cy;

			x += dimension.cx;
			if ( x > pGraphic->width )
			{
				x = 0;
				y += maxY;
			}
		}
	}
}



void CShapeView::OnInitialUpdate()
{
	CScrollView::OnInitialUpdate();

	CSize sizeTotal;
	// TODO: calculate the total size of this view
	sizeTotal.cx = 640;
	sizeTotal.cy = 480;
	SetScrollSizes(MM_TEXT, sizeTotal);

	CShapeDoc* pDoc = (CShapeDoc*)GetDocument();
	// TODO: add draw code here
	if ( !pDoc || !pDoc->GetShapeCount() )
		return;

	m_pGraphic = CreateGraphic( 640, 480, 8, ((const BITMAPINFO *)theApp.m_bitmapInfo)->bmiColors );

	m_pCurShape = pDoc->GetShapeFile( 150, m_nShapeLength );

	if ( m_pCurShape )
	{
		CPoint hotspot;
		CSize dimension;
		GetShapeFrameInfo( m_pCurShape, m_nShapeLength, 0, hotspot, dimension );
		m_pDragImage = CreateGraphic( dimension.cx, dimension.cy, 8, ((const BITMAPINFO *)theApp.m_bitmapInfo)->bmiColors );
		PFRAMEENTRY pFrameEntry = GetShapeFrame( m_pCurShape, m_nShapeLength, 0 );
		DrawShapeFrame( m_pDragImage, pFrameEntry, hotspot.x, hotspot.y );

		m_ilDrag.Create( dimension.cx, dimension.cy, ILC_COLOR24, 0, 16 ); // no effect for ILC_COLOR8 or ILC_COLOR24
		int idx = m_ilDrag.Add( CBitmap::FromHandle(m_pDragImage->hBitmap), RGB(0,0,0) );
		DeleteGraphic(m_pDragImage);
		m_pDragImage = NULL; // it's no problem to delete the image after it is added to the imagelist.
	}

	m_nCurShapeIndex = 0;
	long shapeLength;
	PSHAPEENTRY shapeEntry = pDoc->GetShapeFile( m_nCurShapeIndex, shapeLength );
	DrawShapeList( m_pGraphic, shapeEntry, shapeLength );

	int nFrameCount = GetShapeFrameCount( shapeEntry, shapeLength );

	CString sTitle;
	sTitle = pDoc->GetTitle();
	int dash = sTitle.ReverseFind(_T('-'));
	if ( dash > 0 )
		sTitle = sTitle.Left(dash-1);
	CString newTitle;
	newTitle.Format(_T("%s-%d:%d"), sTitle, m_nCurShapeIndex, nFrameCount );
	pDoc->SetTitle(newTitle);
}

void CShapeView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
	if ( m_pGraphic )
	{
		::StretchDIBits(
			pDC->GetSafeHdc(),
			0, 0, m_pGraphic->width, m_pGraphic->height,
			0, 0, m_pGraphic->width, m_pGraphic->height,
			m_pGraphic->pBits,
			&m_pGraphic->bmInfo,
			DIB_RGB_COLORS,
			SRCCOPY );
	}
	/*
	if ( m_pDragImage )
	{
		::StretchDIBits(
			pDC->GetSafeHdc(),
			200, 200, m_pDragImage->width, m_pDragImage->height,
			0, 0, m_pDragImage->width, m_pDragImage->height,
			m_pDragImage->pBits,
			&m_pDragImage->bmInfo,
			DIB_RGB_COLORS,
			SRCCOPY );
	}*/
}


// CShapeView diagnostics

#ifdef _DEBUG
void CShapeView::AssertValid() const
{
	CScrollView::AssertValid();
}

#ifndef _WIN32_WCE
void CShapeView::Dump(CDumpContext& dc) const
{
	CScrollView::Dump(dc);
}
#endif
#endif //_DEBUG


// CShapeView message handlers


BOOL CShapeView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: Add your message handler code here and/or call default
	// return CScrollView::OnEraseBkgnd(pDC);
	CRect rc;
	GetClientRect(rc);

	CSize sz = GetTotalSize();

	if ( rc.Width() > sz.cx )
	{
		pDC->FillSolidRect( sz.cx, 0, rc.Width() - sz.cx, sz.cy, RGB(200,200,200) );
	}

	if ( rc.Height() > sz.cy )
	{
		pDC->FillSolidRect( 0, sz.cy, rc.Width(), rc.Height() - sz.cy, RGB(200,200,200) );
	}

	return TRUE;
}

void CShapeView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CScrollView::OnLButtonDown(nFlags, point);

	if ( GetDocument()->GetTitle().Left(10) != _T("SHAPES.VGA") )
		return;

	if ( !m_pCurShape || IsShapeTile( m_pCurShape, m_nShapeLength ) )
		return;

	/*
	CPoint ptOrigin = GetScrollPosition();
	point += ptOrigin;

	PFRAMEENTRY pFrameEntry = (PFRAMEENTRY)((char*)m_pCurShape + m_pCurShape->offset[m_nFrameIndex]);

	bool hit = HitTest( pFrameEntry, m_nCurAnchorX, m_nCurAnchorY, point.x, point.y );

	if ( !hit )
	{
		ClearGraphic(m_pGraphic);
		m_nCurAnchorX = point.x;
		m_nCurAnchorY = point.y;
		DrawShape( m_pGraphic, m_pCurShape, m_nShapeLength, m_nFrameIndex, m_nCurAnchorX, m_nCurAnchorY );
		Invalidate();
	}*/

	BOOL b = m_ilDrag.BeginDrag( 0, CPoint(0,0) );
	if (!b)
		TRACE("Failed to BeginDrag!!!\n");
	else
	{
		CPoint ptScr(point);
		ClientToScreen(&ptScr);
		b = m_ilDrag.DragEnter( NULL, ptScr );
		if (!b)
			TRACE("Failed to DragEnter!!!\n");
	}		

	SetCapture();
	m_bDragged = true;
}


void CShapeView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CScrollView::OnLButtonUp(nFlags, point);

	if (m_bDragged)
	{
		BOOL b = m_ilDrag.DragLeave(NULL);
		if (!b)
			TRACE("Failed to DragLeave!!!\n");

		m_ilDrag.EndDrag();
		ReleaseCapture();
		m_bDragged = false;
	}
}


void CShapeView::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CScrollView::OnMouseMove(nFlags, point);

	if (m_bDragged)
	{
		CPoint ptScr(point);
		ClientToScreen(&ptScr);
		BOOL b = m_ilDrag.DragMove( ptScr );
		if (!b) 
			TRACE("Failed to DragMove!!!\n");
	}
}

void CShapeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: Add your message handler code here and/or call default
	CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);

	CShapeDoc* pDoc = (CShapeDoc*)GetDocument();
	int nShapeCount = pDoc->GetShapeCount();

	switch (nChar) {
	case VK_UP:
		if ( m_nCurShapeIndex > 0 )
		{
			--m_nCurShapeIndex;
		}		
		break;
	case VK_DOWN:
		if ( m_nCurShapeIndex < nShapeCount - 1 )
		{
			++m_nCurShapeIndex;
		}
		break;
	}

	PSHAPEENTRY shapeEntry;
	long shapeLength;

	shapeEntry = pDoc->GetShapeFile( m_nCurShapeIndex, shapeLength );

	DrawShapeList( m_pGraphic, shapeEntry, shapeLength );
	Invalidate(0);

	int nFrameCount = GetShapeFrameCount( shapeEntry, shapeLength );

	CString sTitle;
	sTitle = pDoc->GetTitle();
	int dash = sTitle.ReverseFind(_T('-'));
	if ( dash > 0 )
		sTitle = sTitle.Left(dash);
	CString newTitle;
	newTitle.Format(_T("%s-%d:%d"), sTitle, m_nCurShapeIndex, nFrameCount );
	pDoc->SetTitle(newTitle);
}
